#!coding:utf-8
# vim: tabstop=4 shiftwidth=4 softtabstop=4
from lxml import etree
from cvirt.common import exception
import logging
import os

LOG = logging.getLogger(__name__)
"""
    @author jay.han

    libvirt schema:
    basictypes.rng  domaincommon.rng  domainsnapshot.rng  networkcommon.rng  nodedev.rng   secret.rng             storagepool.rng
    capability.rng  domain.rng        interface.rng       network.rng        nwfilter.rng  storageencryption.rng  storagevol.rng

"""

rng_path = "/usr/share/libvirt/schemas/%s.rng"



class XmlObject(object):
    RNG_NAME = None
    ns_prefix = None
    ns_uri = None
    def __init__(self, parse_xml=None, **kw):
        "注意：子类传入的属性参数会被parse_xml中的属性覆盖"
        if not self.ns_prefix:
            self.ns_prefix = kw.get('ns_prefix')
        if not self.ns_uri:
            self.ns_uri = kw.get('ns_uri')
        if self.RNG_NAME:
            self.relaxng = etree.RelaxNG(file=(rng_path % self.RNG_NAME))

        if parse_xml:
            self.parse_xml(parse_xml)

    def _set_attr(self, **kw):
        "@todo remove this method, parameter of class __init__ should be clear"

        for key, value in kw.items():
            if hasattr(self, key):
                setattr(self, key, value)

    def _set_text(self, name, value):
        child = etree.Element(name)
        child.text = str(value)
        return child

    def _create_new_context(self):
        "create new xml context"
        if self.ns_uri is None:
            return etree.Element(self.ROOT_NAME)
        else:
            # etree.register_namespace(self.ns_prefix, self.ns_uri)

            return etree.Element(self.ROOT_NAME, nsmap={self.ns_prefix:self.ns_uri})

    def _get_xml_config(self, root):
        '''
        @param root: lxml object
        @return:
        '''
        raise NotImplemented()

    def _parse_xml(self, xmldoc):
        raise NotImplemented()


    def get_xml_config(self):
        "对外暴露的获取xml对象方法"
        xmlobject = self._get_xml_config(root=self._create_new_context())
        self.validate(xmlobject)
        return xmlobject

    def parse_xml(self, xmlstr):
        "对外暴露的解析xml方法"
        self.root = etree.fromstring(xmlstr)
        self.validate(self.root)
        self._parse_xml(self.root)


    def validate(self, xmldoc):
        "利用libvirt的schema进行xml验证"
        if self.RNG_NAME:
            validates,error_log = self.relaxng.validate(xmldoc),self.relaxng.error_log
            if not validates:
                raise exception.Error(error_log)

    def to_xml(self, pretty_print=True):
        "对外暴露的获取xml字符串方法"
        root = self.get_xml_config()
        xml_str = etree.tostring(root, pretty_print=pretty_print)
        # LOG.debug("Generated XML %s " % xml_str)
        return xml_str


class GuestDevice(XmlObject):
    def __init__(self, parse_xml=None, **kw):
        super(GuestDevice, self).__init__(parse_xml=parse_xml, **kw)